import { ref, watch, onUnmounted, computed } from 'vue'
import { refToRaw, isDocumentVisibility } from '../../utils'
import { subscribe } from '../../utils/listener'
import { isNil } from 'lodash-es'

import type { FP } from '../../types'
import type { Timer } from '../../types/utils'

const usePollingPlugin: FP = (fetchInstance, { pollingInterval, pollingWhenHidden = false }) => {
  const pollingTimer = ref<() => void>()
  const stopPollingWhenHidden = ref(false)
  const pollingIntervalRef = computed(() => refToRaw(pollingInterval))

  const unsubscribeList: (() => void)[] = []
  const addUnsubscribeList = (event?: () => void) => {
    event && unsubscribeList.push(event)
  }

  const isKeepPolling = () => {
    // 当 pollingWhenHidden = true 或者 "屏幕可见时" 轮询
    return pollingWhenHidden || isDocumentVisibility()
  }

  const polling = (pollingFunc: () => void) => {
    let timerId: Timer | undefined
    if (!isNil(pollingIntervalRef.value) && pollingIntervalRef.value >= 0) {
      if (isKeepPolling()) {
        timerId = setTimeout(pollingFunc, pollingIntervalRef.value)
      } else {
        // 停止轮询
        stopPollingWhenHidden.value = true
        return
      }
    }
    return () => timerId && clearTimeout(timerId)
  }

  const rePolling = () => {
    if (stopPollingWhenHidden.value && isKeepPolling()) {
      fetchInstance.context.refresh()
      stopPollingWhenHidden.value = false
    }
  }

  watch(pollingIntervalRef, () => {
    if (pollingTimer.value) {
      pollingTimer.value()
      pollingTimer.value = polling(() => fetchInstance.context.refresh())
    }
  })

  if (!pollingWhenHidden) {
    addUnsubscribeList(subscribe('VISIBLE_LISTENER', rePolling))
  }

  onUnmounted(() => {
    unsubscribeList.forEach(unsubscribe => unsubscribe())
    unsubscribeList.length = 0
  })

  return {
    onBefore() {
      pollingTimer.value?.()
    },
    onAfter() {
      pollingTimer.value = polling(() => fetchInstance.context.refresh())
    },
    onCancel() {
      pollingTimer.value?.()
    }
  }
}

export default usePollingPlugin
